using UnityEngine;
using System.Collections;

/// \class  gkAbyssalGiantPlantMeshBlender
/// \brief  Blend the plant mesh
[AddComponentMenu("GK/AbyssalGiant/Plant/gkAbyssalGiantPlantMeshBlender")]
public class gkAbyssalGiantPlantMeshBlender : MonoBehaviour 
{
	/// The Target in local space
	public Vector3 LocalTargetOffset = Vector3.zero;
	
	public float Pow = 1.5f;
	
	/// The orignal height of the plant
	private float m_fOriginalHeight;
	
	/// The working mesh
    private Mesh m_rWorkingMesh;
    
	/// The original mesh
	private Mesh m_rOriginalMesh;
   
	 /// \brief  Called just after the game begin to play
    void Start()
	{
        MeshFilter filter;
		
		// Grab the mesh filter		
		filter = GetComponent<MeshFilter>();
        
		// Grab the original mesh
		m_rOriginalMesh= filter.sharedMesh;
		
		// Grab the working mesh
        m_rWorkingMesh = filter.mesh;
		
		// Compute the original height of the plant
		m_fOriginalHeight = renderer.bounds.size.y;
    }

	/// \brief  Update is called once per frame
    void Update()
    {
        Vector3[] rWorkingMeshVertexPositions; 
		float fYScale;
		Vector3 f3LocalTarget;
		
		f3LocalTarget = LocalTargetOffset;
		f3LocalTarget.y += m_fOriginalHeight;
		
		/// Initialize the working vertixes with the orignial mesh vertices
		rWorkingMeshVertexPositions = m_rOriginalMesh.vertices;
		
		// Compute the height extension
		fYScale = f3LocalTarget.y/m_fOriginalHeight;
		
		// loop through the vertices and move them
        for(int i = 0; i < rWorkingMeshVertexPositions.Length; i++)
        {	
			float fTangentCoefficient;
			Vector3 f3RadialOffset;
			Vector3 f3VertexPositionNew;
			Vector3 f3CurvatureRadialVector;
			Vector3 f3VertexPositionOriginalScaled;
			
			// Get the original vertex position scaled in height
			f3VertexPositionOriginalScaled = rWorkingMeshVertexPositions[i];
			f3VertexPositionOriginalScaled.y *= fYScale;
			
			// If the vertex is in the positive height move it accordingly to the blend
			if(f3VertexPositionOriginalScaled.y > 0)
			{
				// Compute the tangent coefficient
				fTangentCoefficient = -f3LocalTarget.x/(Mathf.Pow(f3LocalTarget.y, Pow)) 
					* Pow * Mathf.Pow(f3VertexPositionOriginalScaled.y, Pow - 1);
				
				// Compute the radial normal vector
				f3CurvatureRadialVector = Vector3.zero;
				f3CurvatureRadialVector.y = fTangentCoefficient;
				f3CurvatureRadialVector.x = 1.0f;
				f3CurvatureRadialVector.Normalize();
					
				// Compute the radial offset based on the normal vector
				f3RadialOffset = f3CurvatureRadialVector * f3VertexPositionOriginalScaled.x;
				
				// Compute the New vertex position
				f3VertexPositionNew = f3VertexPositionOriginalScaled;
				
				// Compute The curve center
				f3VertexPositionNew.x = Mathf.Pow(f3VertexPositionOriginalScaled.y, Pow) * f3LocalTarget.x/(Mathf.Pow(f3LocalTarget.y, Pow));
				
				// Add the radial offset to the curve center
				f3VertexPositionNew += f3RadialOffset;
				
				// Apply the transformation
				rWorkingMeshVertexPositions[i] = f3VertexPositionNew;
			}
		}

        m_rWorkingMesh.vertices = rWorkingMeshVertexPositions;
        m_rWorkingMesh.RecalculateBounds();
    }
}
